package cn.demoncat.util.lang;

import cn.demoncat.util.exception.ReflexRuntimeException;
import cn.demoncat.util.lang.constant.StringConstant;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.reflections.ReflectionUtils;

import java.lang.reflect.Method;
import java.util.Set;
import java.util.function.Predicate;

/**
 * 反射Method工具
 * 
 * @author 延晓磊
 *
 * @since 2019年11月25日
 */
public class ReflectMethodUtil {

	/**
	 * 获取Method的信息
	 * 
	 * @return 类名.方法名(参数,参数)
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年8月16日
	 */
	public static String toString(Method method) {
		return toString(method, true);
	}
	
	/**
	 * 获取Method的信息
	 * 
	 * @param hasParams	是否展示参数
	 * 
	 * @return 类名.方法名(参数,参数)
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年8月16日
	 */
	public static String toString(Method method, boolean hasParams) {
		// 类名.方法名
		StringBuilder sd = new StringBuilder().append(method.getDeclaringClass().getName()).append(StringConstant.POINT).append(method.getName());
		// (参数,参数)
		if (hasParams) {
			sd.append(StringConstant.LEFT_BRACKET);
			for (int i = 0; i < method.getParameterTypes().length; i++) {
				if (i > 0) {
					sd.append(StringConstant.COMMA);
				}
				sd.append(method.getParameterTypes()[i].getSimpleName());
			}
			sd.append(StringConstant.RIGHT_BRACKET);
		}
		return sd.toString();
	}
	
	/**
	 * 根据字段名，获取get方法
	 * 
	 * 
	 * @param fieldName	字段名
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年9月25日
	 */
	public static String fieldGetMethod(String fieldName) {
		return "get" + StringUtil.firstUpper(fieldName);
	}

	/**
	 * 根据字段名，获取set方法
	 * 
	 * 
	 * @param fieldName	字段名
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2019年9月25日
	 */
	public static String fieldSetMethod(String fieldName) {
		return "set" + StringUtil.firstUpper(fieldName);
	}
	
	/**
	 * 获取声明方法，不包含继承字段
	 * 
	 * @param type			类型
	 * @param predicates	筛选条件
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年2月1日
	 */
	@SafeVarargs
	public static Set<Method> getMethods(final Class<?> type, Predicate<? super Method>... predicates) {
       return ReflectionUtils.getMethods(type, predicates);
    }
    
	/**
	 * 获取全部方法 ，包含继承字段
	 * 
	 * @param type			类型
	 * @param predicates	筛选条件
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年2月1日
	 */
	@SafeVarargs
	public static Set<Method> getAllMethods(final Class<?> type, Predicate<? super Method>... predicates) {
       return ReflectionUtils.getAllMethods(type, predicates);
    }

	/**
	 * 判断方法是否返回 void
	 *
	 * @param method
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2020年2月1日
	 */
	public static boolean isReturnVoid(Method method){
		return method.getReturnType().equals(Void.TYPE);
	}

	/**
	 * 执行方法
	 *
	 * @param object 	invoke method on this object
	 * @param method 	get method with this name
	 * @param args		use these arguments - treat null as empty array
	 *
	 * @return The value returned by the invoked method
	 *
	 * @author 延晓磊
	 * @since 2022年06月22日
	 */
	public static Object invoke(Object object, String method, Object... args){
		try {
			return ArrayUtils.isEmpty(args) ? MethodUtils.invokeMethod(object, method) : MethodUtils.invokeMethod(object, method, args);
		} catch (Exception e) {
			throw new ReflexRuntimeException("执行方法失败：" + method, e);
		}
	}
}
